package com.znjc.device.websocket;


import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONObject;
import com.znjc.common.constant.DeviceConstants;
import com.znjc.device.service.IDeviceCommandService;
import com.znjc.device.service.IDeviceDeviceService;
import com.znjc.device.service.IIotSerialService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.Semaphore;

/**
 * websocket 消息处理
 *
 * @author ruoyi
 */
@Component
@ServerEndpoint("/websocket/message/{clientId}")
@Slf4j
public class WebSocketServer {
    @Resource
    IIotSerialService iotSerialService;
    @Resource
    IDeviceCommandService deviceCommandService;
    @Resource
    IDeviceDeviceService deviceDeviceService;

    public IIotSerialService getIotSerialService() {
        if(null == iotSerialService){
            iotSerialService = SpringUtil.getBean(IIotSerialService.class);
        }
        return iotSerialService;
    }

    public IDeviceCommandService getDeviceCommandService() {
        if(null == deviceCommandService){
            deviceCommandService = SpringUtil.getBean(IDeviceCommandService.class);
        }
        return deviceCommandService;
    }

    public IDeviceDeviceService getDeviceDeviceService() {
        if(null == deviceDeviceService){
            deviceDeviceService = SpringUtil.getBean(IDeviceDeviceService.class);
        }
        return deviceDeviceService;
    }

    /**
     * 默认最多允许同时在线人数100
     */
    public static int socketMaxOnlineCount = 100;



    private static Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);

    /**
     * session
     */
    private Session session;

    /**
     * 客户端端标识
     */
    private String clientId;
    /**
     * 在线数
     */
    private static int onlineCount = 0;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("clientId") String clientId, Session session) throws Exception {
        this.clientId = clientId;
        this.session = session;
        boolean semaphoreFlag = false;
        // 尝试获取信号量
        semaphoreFlag = SemaphoreUtils.tryAcquire(socketSemaphore);
        if (!semaphoreFlag) {
            // 未获取到信号量
            log.error("\n 当前在线人数超过限制数- {}", socketMaxOnlineCount);
            WebSocketUsers.sendMessageToUserByText(session, "当前在线人数超过限制数：" + socketMaxOnlineCount);
            session.close();
        } else {
            // 添加用户
            WebSocketUsers.put(clientId, session);
            log.info("\n 建立连接 - {}", session);
            log.info("\n 当前人数 - {}", WebSocketUsers.getUsers().size());
            WebSocketUsers.sendMessageToUserByText(session, "连接成功");
            if("9998".equals(clientId)){
                JSONObject data = getDeviceDeviceService().updateDeviceDataWs();
                WebSocketUsers.sendMessageToUserByText(clientId,data.toJSONString());
            }
        }
    }

    /**
     * 连接关闭时处理
     */
    @OnClose
    public void onClose(Session session) {
        log.info("\n 关闭连接 - {}", session);
        // 移除用户
        WebSocketUsers.remove(clientId);
        if(!clientId.contains("999")){
            getIotSerialService().closeGather(Long.parseLong(clientId));
        }
        // 获取到信号量则需释放
        SemaphoreUtils.release(socketSemaphore);
    }

    /**
     * 抛出异常时处理
     */
    @OnError
    public void onError(Session session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            // 关闭连接
            session.close();
        }
        String sessionId = session.getId();
        log.info("\n 连接异常 - {}", sessionId);
        log.info("\n 异常信息 - {}", exception);
        // 移出用户
        WebSocketUsers.remove(clientId);
        // 获取到信号量则需释放
        SemaphoreUtils.release(socketSemaphore);
    }

    /**
     * 服务器接收到客户端消息时调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info(message);
        JSONObject data = JSONObject.parseObject(message);
        if (!data.isEmpty()) {
            if (data.containsKey("vue_msg")) {
                WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9999, message);
            } else if (data.containsKey("needData")) {
                try {
                    if(data.containsKey("commandId")){
                        //解析命令设置是否成功
                        getDeviceCommandService().analyzeData(data);
                    }else{
                        //解析读到的实时数据
                        getIotSerialService().analyzeData(data);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //WebSocketUsers.sendMessageToUserByText(session, message);
    }


}


